using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using System.Collections.Generic;
using Microsoft.SharePoint.Navigation;

namespace Microsoft.OpportunityPortal.Features.OpportunitySecurity
{
    /// <summary>
    /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
    /// </summary>
    /// <remarks>
    /// The GUID attached to this class may be used during packaging and should not be modified.
    /// </remarks>

    [Guid("390713d2-8d16-4d28-b413-3a8549acdfb0")]
    public class OpportunitySecurityEventReceiver : SPFeatureReceiver
    {
        // Uncomment the method below to handle the event raised after a feature has been activated.
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            string portalSiteURL = string.Empty;

            // Retrieve the current site URL
            if (properties.Feature.Parent != null && properties.Feature.Parent is SPSite)
            {
                portalSiteURL = ((SPSite)properties.Feature.Parent).OpenWeb().Url;
            }
            else if (properties.Feature.Parent != null && properties.Feature.Parent is SPWeb)
            {
                portalSiteURL = ((SPWeb)properties.Feature.Parent).Url;
            }

            try
            {
                // associate approval and review workflows with Opportunity Requests content type
                this.AssociateWorkflows(properties);

                // Delete the unnecessary URLs and update the create opportunity url
                this.UpdateNavigationLinks(portalSiteURL, "Create Opportunity");

                SPRoleDefinition roleDef = new SPRoleDefinition();
                roleDef.BasePermissions = SPBasePermissions.ManageLists |
                SPBasePermissions.AddListItems |
                SPBasePermissions.EditListItems |
                SPBasePermissions.DeleteListItems |
                SPBasePermissions.ViewListItems |
                SPBasePermissions.OpenItems |
                SPBasePermissions.ManagePermissions |
                SPBasePermissions.ManageSubwebs |
                SPBasePermissions.ManageWeb |
                    SPBasePermissions.CreateGroups;

                // Create SubSite Creation Permission level
                bool result = SPOperations.CreatePermissionLevel(properties.UserCodeSite.Url, "Manage Opportunity SubSite", "Manage Opportunity Permission", roleDef);

                if (result == true)
                {
                    // Create group and assign SubSite Creation Permission level
                    SPOperations.CreateGroup(properties.UserCodeSite.Url, portalSiteURL, "Members", "Manage Opportunity Sites", "Manage Opportunity SubSite");
                }

                // Create Reviewers and Approvers group
                SPOperations.CreateGroup(portalSiteURL, properties.UserCodeSite.Url, "Reviewers", "Contribute", SPRoleType.Contributor, null,
                    true, string.Empty);
                SPOperations.CreateGroup(portalSiteURL, properties.UserCodeSite.Url, "Approvers", "Contribute", SPRoleType.Contributor, null,
                    true, string.Empty);
            }
            catch (SPException expn)
            {
                Dictionary<string, string> errorLog = new Dictionary<string, string>();
                errorLog.Add("Title", "Error_" + DateTime.Now.ToLongTimeString());
                errorLog.Add("Description", string.Format("StackTrace={0},Message={1}", expn.StackTrace, expn.Message));
                errorLog.Add("EventType", "Error");

                SPOperations.AddUpdateListItem(portalSiteURL, "Logger", errorLog, SPEventType.Add);
            }
        }

        private void AssociateWorkflows(SPFeatureReceiverProperties properties)
        {
            try
            {
                SPWeb web = null;

                if (properties.Feature.Parent is SPWeb)
                {
                    web = properties.Feature.Parent as SPWeb;
                }
                else if (properties.Feature.Parent is SPSite)
                {
                    web = (properties.Feature.Parent as SPSite).OpenWeb();
                }

                if (web != null)
                {
                    string taskListTitle = "Tasks";
                    string contentTypeName = "Opportunity Requests";
                    string historyListTitle = "Workflow History";
                    string approvalWFName = "Opportunity Approval Workflow";
                    string reviewWFName = "Opportunity Review Workflow";

                    SPOperations.AssociateWorkflow(web.Url, contentTypeName, approvalWFName, taskListTitle, historyListTitle);
                    SPOperations.AssociateWorkflow(web.Url, contentTypeName, reviewWFName, taskListTitle, historyListTitle);

                    // Dispose SPWeb object
                    web.Dispose();
                }
            }
            catch (SPException)
            {
                // throw new Exception("Check whether Approval and Review Opportunity workflow features are installed.");
            }
        }

        private void UpdateNavigationLinks(string siteURL, string headerName)
        {
            try
            {
                using (SPSite site = new SPSite(siteURL))
                {
                    using (SPWeb web = site.OpenWeb())
                    {
                        SPNavigation nav = web.Navigation;
                        SPNavigationNodeCollection nodeColln = nav.QuickLaunch;

                        foreach (SPNavigationNode node in nodeColln)
                        {
                            string name = node.Title;
                            string url = node.Url;

                            if (string.Compare(name, headerName, true) == 0)
                            {
                                // Get the listID contains inside the closing braces
                                int startChar = url.LastIndexOf('{');
                                int endChar = url.LastIndexOf('}');

                                // Get the Opportunity Request ID
                                SPList requestList = web.Lists["Opportunity Requests"];

                                if (startChar > 0 && endChar > 0 && endChar > startChar && requestList != null)
                                {
                                    string strToReplace = url.Substring(startChar, endChar - startChar + 1);
                                    url = url.Replace(strToReplace, requestList.ID.ToString());
                                }

                                node.Url = url;
                                node.Update();
                            }
                            else
                            {
                                node.Delete();
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                // Kill the unknown exception
            }
        }

        // Uncomment the method below to handle the event raised before a feature is deactivated.

        //public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        //{
        //}


        // Uncomment the method below to handle the event raised after a feature has been installed.

        //public override void FeatureInstalled(SPFeatureReceiverProperties properties)
        //{
        //}


        // Uncomment the method below to handle the event raised before a feature is uninstalled.

        //public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
        //{
        //}

        // Uncomment the method below to handle the event raised when a feature is upgrading.

        //public override void FeatureUpgrading(SPFeatureReceiverProperties properties, string upgradeActionName, System.Collections.Generic.IDictionary<string, string> parameters)
        //{
        //}
    }
}
